/*
 * @[H]:  Copyright (c) 2021 Phytium Information Technology, Inc. 
 * 
 *  SPDX-License-Identifier: Apache-2.0. 
 * 
 * @Date: 2021-07-12 18:43:00
 * @LastEditTime: 2021-07-15 21:40:20
 * @Description:  Description of file
 * @Modify History: 
 * * * Ver   Who        Date         Changes
 * * ----- ------     --------    --------------------------------------
 */

#include "f_gpio.h"
#include "f_gpio_hw.h"
#include <string.h>
void FGpioSetDirection(FGpio *instance_p, u32 pin, fsize_t direction)
{
    FT_ASSERTVOID(instance_p != NULL);
    FT_ASSERTVOID(instance_p->is_ready == FT_COMPONENT_IS_READY);
    FT_ASSERTVOID(pin < F_GPIO_PIN_MAX_NUM);
    u32 val;
    FGpioConfig *config_p;
    config_p = &instance_p->config;

    if (pin < F_GPIO_B_PIN0)
    {
        val = FGPIO_READREG32(config_p->base_address, GPIO_SWPORTA_DDR_OFFSET);
    }
    else
    {
        val = FGPIO_READREG32(config_p->base_address, GPIO_SWPORTB_DDR_OFFSET);
    }

    switch (direction)
    {
    case F_GPIO_DIRECTION_INPUT:
        val &= ~(1 << (pin % 8));
        break;
    case F_GPIO_DIRECTION_OUTPUT:
        val |= (1 << (pin % 8));
        break;
    default:
        return;
    }

    if (pin < 8)
    {
        FGPIO_WRITEREG32(config_p->base_address, GPIO_SWPORTA_DDR_OFFSET, val);
    }
    else
    {
        FGPIO_WRITEREG32(config_p->base_address, GPIO_SWPORTB_DDR_OFFSET, val);
    }
}

fsize_t FGpioGetDirection(FGpio *instance_p, u32 pin)
{
    FT_ASSERTZERONUM(instance_p != NULL);
    FT_ASSERTZERONUM(instance_p->is_ready == FT_COMPONENT_IS_READY);
    FT_ASSERTZERONUM(pin < F_GPIO_PIN_MAX_NUM);
    u32 val;
    FGpioConfig *config_p;
    config_p = &instance_p->config;

    if (pin < F_GPIO_B_PIN0)
    {
        val = FGPIO_READREG32(config_p->base_address, GPIO_SWPORTA_DDR_OFFSET);
    }
    else
    {
        val = FGPIO_READREG32(config_p->base_address, GPIO_SWPORTB_DDR_OFFSET);
    }

    return (val & (1 << (pin % 8))) ? F_GPIO_DIRECTION_OUTPUT : F_GPIO_DIRECTION_INPUT;
}

void FGpioSetValue(FGpio *instance_p, u32 pin, FGpioOutLevel Level)
{
    FT_ASSERTVOID(instance_p != NULL);
    FT_ASSERTVOID(instance_p->is_ready == FT_COMPONENT_IS_READY);
    FT_ASSERTVOID(pin < F_GPIO_PIN_MAX_NUM);
    u32 val;
    FGpioConfig *config_p;
    config_p = &instance_p->config;

    if (pin < F_GPIO_B_PIN0)
    {
        val = FGPIO_READREG32(config_p->base_address, GPIO_SWPORTA_DR_OFFSET);
    }
    else
    {
        val = FGPIO_READREG32(config_p->base_address, GPIO_SWPORTB_DR_OFFSET);
    }

    switch (Level)
    {
    case F_GPIO_OUTPUT_LOW:
        val &= ~(1 << (pin % 8));
        break;
    case F_GPIO_OUTPUT_HIGH:
        val |= (1 << (pin % 8));
        break;
    default:
        return;
    }

    if (pin < F_GPIO_B_PIN0)
    {
        FGPIO_WRITEREG32(config_p->base_address, GPIO_SWPORTA_DR_OFFSET, val);
    }
    else
    {
        FGPIO_WRITEREG32(config_p->base_address, GPIO_SWPORTB_DR_OFFSET, val);
    }
}

fsize_t FGpioGetValue(FGpio *instance_p, u32 pin)
{
    FT_ASSERTZERONUM(instance_p != NULL);
    FT_ASSERTZERONUM(instance_p->is_ready == FT_COMPONENT_IS_READY);
    FT_ASSERTZERONUM(pin < F_GPIO_PIN_MAX_NUM);
    u32 val;
    FGpioConfig *config_p;
    config_p = &instance_p->config;

    if (pin < F_GPIO_B_PIN0)
    {
        val = FGPIO_READREG32(config_p->base_address, GPIO_EXT_PORTA_OFFSET);
    }
    else
    {
        val = FGPIO_READREG32(config_p->base_address, GPIO_EXT_PORTB_OFFSET);
    }

    return (val >> (pin % 8)) & 0x01;
}

ft_error_t FGpioCfgInitialize(FGpio *instance_p, FGpioConfig *config_p)
{
    FT_ASSERTNONVOID(instance_p != NULL);
    memset(instance_p, 0, sizeof(FGpio));
    instance_p->config = *config_p;
    instance_p->is_ready = FT_COMPONENT_IS_READY;
}